package org.rency.ues.annotation.service.impl;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.rency.ues.annotation.service.EncryptService;
import org.rency.ues.annotation.support.AnnotationUtils;
import org.rency.ues.annotation.support.AnnotionData;
import org.rency.ues.annotation.support.MultiAnnotionData;
import org.rency.ues.client.UesClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

import static org.rency.ues.annotation.support.AnnotationUtils.isEmptyObject;

/**
 * @author: Created by user_rcy@163.com on 2016/8/3.
 */
public class EncryptServiceImpl implements EncryptService {

    private static final Logger logger = LoggerFactory.getLogger(EncryptServiceImpl.class);

    private UesClient uesClient;

    @Override
    public Object[] process(Object[] params, MultiAnnotionData miad) throws Exception {
        if(ArrayUtils.isEmpty(params)){
            return null;
        }
        Map<Object, AnnotionData> iad = miad.getAnnotionDatas();
        if(MapUtils.isEmpty(iad)){
            return null;
        }

        List<Object> list = new ArrayList<Object>(params.length);
        AnnotionData ad = null;
        for (Object obj : params) {
            if (!isEmptyObject(obj)) {
                ad = iad.get(obj);
                if(ad == null){
                    continue;
                }
                encrypt(ad.getIncludeFields(),obj);
            }
            list.add(obj);
        }
        return list.toArray();
    }

    private void encrypt(List<String> includeFields, Object obj) throws Exception {
        if(CollectionUtils.isEmpty(includeFields)){
            return;
        }
        if(AnnotationUtils.isCollection(obj)){
            if (obj.getClass().isArray()) {
                Object[] arr = (Object[]) obj;
                for (int i = 0; i < arr.length; i++) {
                    encryptObject(arr[i], includeFields);
                }
            } else {
                Collection<?> col = (Collection<?>) obj;
                Iterator<?> it = col.iterator();
                Object item = null;
                while (it.hasNext()) {
                    item = it.next();
                    encryptObject(item, includeFields);
                }
            }
        }else{
            encryptObject(obj, includeFields);
        }
    }

    private Object encryptObject(Object arg, List<String> includeFields) throws Exception {
        //远程加密
        Map<String, String> ticketMap = uesClient.encrypt(this.getPlainDatas(arg,includeFields));
        if(MapUtils.isEmpty(ticketMap)){
            logger.info("远程UES批量加密返回空.");
            return arg;
        }

        for(String fieldName : includeFields){
            Object value = AnnotationUtils.getFieldValue(arg,fieldName);
            if(value instanceof String){
                String plainData = (String) value;
                AnnotationUtils.setFieldValue(arg,fieldName,ticketMap.get(plainData));
            }
        }
        return arg;
    }

    private List<String> getPlainDatas(Object arg, List<String> includeFields) throws IllegalArgumentException, IllegalAccessException {
        List<String> resultList = new ArrayList<String>(includeFields.size());
        for(int i = 0; i < includeFields.size(); i++){
            String fieldName = includeFields.get(i);
            Object value = AnnotationUtils.getFieldValue(arg,fieldName);
            if (value instanceof String) {
                String plainData = (String) value;
                if(StringUtils.isBlank(plainData)){
                    continue;
                }
                resultList.add(plainData);
            }
        }
        return resultList;
    }

    public void setUesClient(UesClient uesClient) {
        this.uesClient = uesClient;
    }
}
